//+------------------------------------------------------------------------------------------------------------------+
#property description                                                                                     "[XU-STOCH]"
#define Version                                                                                           "[XU-STOCH]"
//+------------------------------------------------------------------------------------------------------------------+
#property link        "https://forex-station.com/viewtopic.php?p=1295409935#p1295409935"
#property description "THIS IS A FREE INDICATOR"
#property description "                                                      "
#property description "Welcome to XARD UNIVERSE"
#property description "Let light shine out of darkness and illuminate your world"
#property description "and with this freedom leave behind your cave of denial"
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_color1  C'121,151,250'
#property indicator_color2  C'250,151,151'
#property indicator_color3  clrAqua
#property indicator_color4  clrOrangeRed
#property indicator_color5  clrOrangeRed
#property indicator_color6  clrNONE
#property indicator_width1  10
#property indicator_width2  10
#property indicator_width3  3
#property indicator_width4  3
#property indicator_width5  3
#property indicator_width6  2
#property indicator_height 0
#property indicator_minimum   0
#property indicator_maximum 100
#property indicator_level1 80
#property indicator_level2 50
#property indicator_level3 20
#property indicator_levelcolor C'91,103,112'
#property indicator_levelstyle 1
enum enColorOn
{
   cc_slo, // Change color on slope change
   cc_sig  // Change color on signal cross
};
extern bool               showNextTF          = false;
extern int                KPeriod             = 45;
extern int                DPeriod             = 45;
input int                 Slowing             = 3;
input enColorOn           ColorOn             = cc_slo;           // Color change on :  
input bool                alertsOn            = false;           // Turn alerts on?
input bool                alertsOnCurrent     = false;          // Alerts on still opened bar?
input bool                alertsMessage       = true;           // Alerts should display message?
input bool                alertsSound         = false;          // Alerts should play a sound?
input bool                alertsNotify        = false;          // Alerts should send a notification?
input bool                alertsEmail         = false;          // Alerts should send an email?
input string              soundFile           = "alert2.wav";   // Sound file
input bool                arrowsVisible       = false;                 // Arrows visible true/false?
input bool                arrowsOnNewest      = true;                 // Arrows drawn on newest bar of higher time frame bar true/false?
input string              UniqueArrowsID      = "ZLStochArrows1";         // Unique ID for arrows
input double              arrowsUpperGap      = 0.5;                  // Upper arrow gap
input double              arrowsLowerGap      = 0.5;                  // Lower arrow gap
input color               arrowsUpColor       = clrLime;         // Up arrow color
input color               arrowsDnColor       = clrGold;           // Down arrow color
input int                 arrowsUpCode        = 241;                  // Up arrow code
input int                 arrowsDnCode        = 242;                  // Down arrow code
input int                 arrowsUpSize        = 4;                    // Up arrow size
input int                 arrowsDnSize        = 4;                    // Down arrow size
extern bool               ShowBackgroundZones = true;

//---- buffers
double sto[],stoda[],stodb[],sig[],wb1[],wb2[],wb3[],stoc[];
double UpBackgroundZone[], DownBackgroundZone[]; string ID="    ";
//+------------------------------------------------------------------------------------------------------------------+
   int OnInit(){IndicatorBuffers(10);  IndicatorShortName(ID);
   if(showNextTF){
   if(Period()==PERIOD_M1) {KPeriod= 14*5.;}
   if(Period()==PERIOD_M5) {KPeriod= 14*3.;}
   if(Period()==PERIOD_M15){KPeriod= 14*2.;}
   if(Period()==PERIOD_M30){KPeriod= 14*2.;}
   if(Period()>=PERIOD_H1) {KPeriod= 14*4.;}}
   SetIndexBuffer(0,UpBackgroundZone); 
   SetIndexBuffer(1,DownBackgroundZone); 
   SetIndexBuffer(2,sto);   SetIndexStyle(2, DRAW_LINE);
   SetIndexBuffer(3,stoda); SetIndexStyle(3, DRAW_LINE);
   SetIndexBuffer(4,stodb); SetIndexStyle(4, DRAW_LINE);
   SetIndexBuffer(5,sig);   SetIndexStyle(5, DRAW_LINE);
   SetIndexBuffer(6,wb1);   SetIndexStyle(6, DRAW_NONE);
   SetIndexBuffer(7,wb2);   SetIndexStyle(7, DRAW_NONE);
   SetIndexBuffer(8,wb3);   SetIndexStyle(8, DRAW_NONE); 
   SetIndexBuffer(9,stoc);  SetIndexStyle(9, DRAW_NONE);
   if(ShowBackgroundZones){
     SetIndexStyle(0,DRAW_HISTOGRAM); 
     SetIndexStyle(1,DRAW_HISTOGRAM);} else {
     SetIndexStyle(0,DRAW_NONE);
     SetIndexStyle(1,DRAW_NONE);}
   for(int Bufx=0;Bufx<indicator_buffers;Bufx++){SetIndexLabel(Bufx,NULL);} return(INIT_SUCCEEDED);}
//+------------------------------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
{ 
///// copy and paste template //////////////////////////////////////////
    string lookFor       = UniqueArrowsID+":";
    int    lookForLength = StringLen(lookFor);
    for (int i=ObjectsTotal()-1; i>=0; i--)
    {
       string objectName = ObjectName(i);
       if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
    }
///// copy and paste template //////////////////////////////////////////
}
//+------------------------------------------------------------------------------------------------------------------+
int  OnCalculate(const int rates_total,const int prev_calculated,const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   int i,limit=fmin(rates_total-prev_calculated+1,rates_total-2); 
   if (stoc[limit]==-1) CleanPoint(limit,stoda,stodb);
   for (i=limit;i>=0; i--)
   { 
      double lo =  low[ArrayMinimum(low, KPeriod,i)];
      double hi = high[ArrayMaximum(high,KPeriod,i)];
             wb1[i] = (hi!=lo) ? 100*((close[i]-lo)/(hi-lo)) : 0;
   }
   for (i=limit;i>=0; i--) wb2[i] = iMAOnArray(wb1,0,Slowing,0,MODE_SMA,i);  
   for (i=limit;i>=0; i--)
   {
       double ema1   = iMAOnArray(wb2,0,Slowing,0,MODE_SMA, i);    
              sto[i] = wb2[i] + wb2[i] - ema1;}
   for (i=limit;i>=0; i--) wb3[i] = iMAOnArray(sto,0,DPeriod,0,MODE_SMA,i);
   for (i=limit;i>=0; i--){
       double ema2   = iMAOnArray(wb3,0,DPeriod,0,MODE_SMA,i);  
              sig[i] = wb3[i] + wb3[i] - ema2; 
              switch(ColorOn){
   case cc_sig: if(i<rates_total-1)  stoc[i] = (sto[i]>50.) ? 1 : (sto[i]<50.) ? -1 : stoc[i+1]; break;
       default: if(i<rates_total-1)  stoc[i] = (sto[i]>50.) ? 1 : (sto[i]<50.) ? -1 : stoc[i+1];}
              stoda[i] = stodb[i] = EMPTY_VALUE; if (stoc[i] == -1) PlotPoint(i,stoda,stodb,sto);           
/// copy and paste template ///////////////////////////////////               
               if (arrowsVisible){
                 string lookFor = UniqueArrowsID+":"+(string)Time[i]; ObjectDelete(lookFor);            
                 if (stoc[i] != stoc[i+1]){
                   if (stoc[i] == 1) drawArrow(i,arrowsUpColor,arrowsUpCode,arrowsUpSize,false);
                   if (stoc[i] ==-1) drawArrow(i,arrowsDnColor,arrowsDnCode,arrowsDnSize, true);
                 }//if (state[i] != state[i+1])
               }//if (arrowsVisible)       
/// copy and paste template ///////////////////////////////////               
               UpBackgroundZone[i] = EMPTY_VALUE;
               DownBackgroundZone[i] = EMPTY_VALUE;
   if(stoc[i] == 1) UpBackgroundZone[i]  = 100; 
   if(stoc[i] ==-1) DownBackgroundZone[i]  = 100;}
   if(alertsOn){int whichBar = (alertsOnCurrent) ? 0 : 1;
   if(stoc[whichBar] != stoc[whichBar+1])
   if(stoc[whichBar] == 1) doAlert(" up"); else doAlert(" down");}  return(0);}
//+------------------------------------------------------------------------------------------------------------------+
   void CleanPoint(int i,double& first[],double& second[]){
   if(i>=Bars-3) return;
   if((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE; else
   if((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;}
//+------------------------------------------------------------------------------------------------------------------+
   void PlotPoint(int i,double& first[],double& second[],double& from[]){if(i>=Bars-2) return;
   if(first[i+1] == EMPTY_VALUE) if(first[i+2] == EMPTY_VALUE) 
            { first[i]  = from[i]; first[i+1]  = from[i+1]; second[i] = EMPTY_VALUE; }
      else  { second[i] = from[i]; second[i+1] = from[i+1]; first[i]  = EMPTY_VALUE; }
   else     { first[i]  = from[i];                          second[i] = EMPTY_VALUE; }}
//+------------------------------------------------------------------------------------------------------------------+
   void doAlert(string doWhat){string msg; static string previousAlert="nothing"; static datetime previousTime;
   if(previousAlert != doWhat || previousTime != Time[0]){previousAlert=doWhat; previousTime=Time[0];
   msg= timeFrameToString(_Period)+" "+_Symbol+" at "+TimeToStr(TimeLocal(),TIME_SECONDS)+" ZeroLag Stoch "+doWhat;
   if(alertsMessage) Alert(msg); if(alertsNotify) SendNotification(msg);
   if(alertsEmail) SendMail(_Symbol+" ZeroLag Stoch ",msg); if(alertsSound) PlaySound(soundFile);}}
//+------------------------------------------------------------------------------------------------------------------+
   string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
   int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};  string timeFrameToString(int tf){
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) if(tf==iTfTable[i]) return(sTfTable[i]); return("");}
//+------------------------------------------------------------------------------------------------------------------+
   void drawArrow(int i,color theColor,int theCode, int theSize, bool up){
   string name = UniqueArrowsID+":"+(string)Time[i];
   double gap  = iATR(NULL,0,20,i); datetime atime = Time[i]; if (arrowsOnNewest) atime += _Period*60-1;      
       ObjectCreate(name,OBJ_ARROW,0,atime,0);
          ObjectSet(name,OBJPROP_ARROWCODE,theCode);
          ObjectSet(name,OBJPROP_COLOR,theColor);
          ObjectSet(name,OBJPROP_WIDTH,theSize);
   if(up) ObjectSet(name,OBJPROP_PRICE1,High[i] + arrowsUpperGap * gap);
     else ObjectSet(name,OBJPROP_PRICE1,Low[i]  - arrowsLowerGap * gap);}
//+------------------------------------------------------------------------------------------------------------------+